using System;
using System.IO;
using System.Xml.Serialization;
using Microsoft.WowAddonStudio.FrameXml.Serialization.Enumerations;
using Microsoft.WowAddonStudio.FrameXml.Serialization.LayoutFrames;
using NUnit.Framework;

namespace Microsoft.WowAddonStudio.FrameXml.Serialization.Tests
{
	[TestFixture]
	public class FrameTest : SerializationTestBase<Frame>
	{
		[Test]
		public void BasicTest()
		{
			InitializeTestEntity("Simple/Frame.xml");

			Assert.AreEqual("TestFrame", TestEntity.Name);
            Assert.IsNotNull(TestEntity.SizeDimension);
			Assert.IsNotNull(TestEntity.Anchors);
		}

		[Test]
		public void TitleRegionTest()
		{
			InitializeTestEntity("Simple/FrameTitleRegion.xml");

			Assert.IsNotNull(TestEntity.TitleRegion);
			Assert.IsTrue(TestEntity.TitleRegion.SetAllPoints);

			AssertNoUnknownElements(TestEntity.TitleRegion);
		}

		[Test]
		public void ResizeBoundsTest()
		{
			InitializeTestEntity("Simple/FrameResizeBounds.xml");

			Assert.IsNotNull(TestEntity.ResizeBounds);
			Assert.IsNotNull(TestEntity.ResizeBounds.MaxResize);
			Assert.IsNotNull(TestEntity.ResizeBounds.MinResize);
			Assert.AreEqual(75, TestEntity.ResizeBounds.MinResize.AbsDimension.Y);

			AssertNoUnknownElements(TestEntity.ResizeBounds);
		}

		[Test]
		public void BackdropTest()
		{
			InitializeTestEntity("Simple/FrameBackdrop.xml");

			Assert.IsNotNull(TestEntity.Backdrop);
			Assert.AreEqual(TestEntity.Backdrop.BackgroundFile, @"Interface\DialogFrame\UI-DialogBox-Background");
			Assert.IsTrue(TestEntity.Backdrop.Tile);

			// BackgroundInsets
			Assert.IsNotNull(TestEntity.Backdrop.BackgroundInset);
			Assert.AreEqual(11, TestEntity.Backdrop.BackgroundInset.Left);

			// TileSize
			Assert.IsNotNull(TestEntity.Backdrop.TileSize);
			Assert.AreEqual(32, TestEntity.Backdrop.TileSize.Value);

			// EdgeSize
			Assert.IsNotNull(TestEntity.Backdrop.EdgeSize);
			Assert.AreEqual(32, TestEntity.Backdrop.EdgeSize.Value);

			// BorderColor / Color
			Assert.IsNotNull(TestEntity.Backdrop.BorderColor);
			Assert.IsNotNull(TestEntity.Backdrop.Color);

			AssertNoUnknownElements(TestEntity.Backdrop);
		}

		[Test]
		public void HitRectInsetTest()
		{
			InitializeTestEntity("Simple/FrameHitRectInset.xml");

			Assert.IsNotNull(TestEntity.HitRectInset);
			Assert.AreEqual(5, TestEntity.HitRectInset.Left);

			AssertNoUnknownElements(TestEntity.HitRectInset);
		}

		[Test]
		public void LayersTest()
		{
			InitializeTestEntity("Simple/FrameLayers.xml");

			Assert.IsNotNull(TestEntity.Layers);
			Assert.AreEqual(2, TestEntity.Layers.Count);
			Assert.AreEqual(DrawLayer.Background, TestEntity.Layers[0].Level);
			Assert.AreEqual(DrawLayer.Artwork, TestEntity.Layers[1].Level);

			Assert.IsNotNull(TestEntity.Layers[0].Items);
			Assert.AreEqual(1, TestEntity.Layers[0].Items.Count);
			Assert.IsTrue(TestEntity.Layers[0].Items[0] is Texture);

			Assert.IsNotNull(TestEntity.Layers[1].Items);
			Assert.AreEqual(1, TestEntity.Layers[1].Items.Count);
			Assert.IsTrue(TestEntity.Layers[1].Items[0] is FontString);

			AssertNoUnknownElements(TestEntity.Layers);
		}

		[Test]
		public void FramesTest()
		{
			InitializeTestEntity("Simple/FrameFrames.xml");

			Assert.IsNotNull(TestEntity.Frames);
			Assert.AreEqual(2, TestEntity.Frames.Count);
			Assert.AreEqual("ChildFrame1", TestEntity.Frames[0].Name);
			Assert.AreEqual("ChildFrame2", TestEntity.Frames[1].Name);

			AssertNoUnknownElements(TestEntity.Frames);

			// TODO: Test with other Frame types as well
		}

		[Test]
		public void ScriptContainerTest()
		{
			InitializeTestEntity("Simple/FrameScripts.xml");

			Assert.IsNotNull(TestEntity.ScriptContainer);
			Assert.AreEqual(2, TestEntity.ScriptContainer.Count);

			Assert.IsNotNull(TestEntity.ScriptContainer[EventName.OnLoad]);
			Assert.IsNotNull(TestEntity.ScriptContainer[EventName.OnLeave]);

			SerializeFrameXml(TestEntity);
		}

		[Test]
		public void ScriptContainerEmptyTest()
		{
			FrameXmlLoader.SchemaPath = string.Empty;

			InitializeTestEntity("Simple/FrameScriptsEmpty.xml");

			Assert.IsNotNull(TestEntity.ScriptContainer);
			Assert.AreEqual(0, TestEntity.ScriptContainer.Count);

			SerializeFrameXml(TestEntity);
		}

		[Test]
		public void ScriptContainerEmptyComplexTest()
		{
			FrameXmlLoader.SchemaPath = string.Empty;

			InitializeTestEntity("Simple/FrameScriptsEmptyComplex.xml");

			Assert.IsNotNull(TestEntity.ScriptContainer);
			Assert.AreEqual(0, TestEntity.ScriptContainer.Count);

			SerializeFrameXml(TestEntity);
		}


		/// <summary>
		/// Serializes the frame XML.
		/// </summary>
		/// <param name="frame">The frame.</param>
		private static void SerializeFrameXml(Frame frame)
		{
			using (var stream = new MemoryStream())
			{
				new XmlSerializer(typeof (Frame)).Serialize(stream, frame);
				stream.Position = 0;
				using (var reader = new StreamReader(stream))
				{
					Console.WriteLine(reader.ReadToEnd());
				}
			}
		}

		/// <summary>
		/// Gets the entity to be tested from a <see cref="Ui"/> instance.
		/// </summary>
		/// <param name="ui">The ui instance.</param>
		/// <returns>
		/// An instance of the <typeparamref name="TSerializationObject"/> class.
		/// </returns>
		protected override Frame GetTestEntity(Ui ui)
		{
			Assert.IsNotNull(ui.LayoutFrames);
			Assert.AreEqual(1, ui.LayoutFrames.Count);

			// Ui/Frame[0]
			Assert.IsTrue(ui.LayoutFrames[0] is Frame);
			return (Frame) ui.LayoutFrames[0];
		}
	}
}